package me.yobol.algorithm.mse.y2015;

/**
 * 罗马数字与阿拉伯数字之间的相互转换
 * 罗马单个数字共有7个，分别为：I（1） V（5） X（10） L（50） C（100） D（500） M（1000）
 * 计数规则为：
 * 规则一：若干相同数字连写表示的数是这些罗马数字的和，如III=3；
 * 规则二：小数字在大数字前面表示的数是用大数字减去小数字，如IV＝4；
 * 规则三：小数字在大数字后面表示的数是用大数字加上小数字，如VI=6;
 * 组合规则为：
 * 基本数字I、X 、C 中的任何一个，自身连用构成数目，或者放在大数的右边连用构成数目，都不能超过三个；而放在大数的左边只能用一个。
 * 转化得到的十进制数字范围为1~3999
 * 
 * 左减的数字有限制，仅限于I、X、C。比如45不可以写成VL，只能是XLV
 * 但是，左减时不可跨越一个位数。比如，99不可以用IC（100 - 1）表示，
 * 而是用XCIX（[100 - 10] + [10 - 1]）表示。（等同于阿拉伯数字每位数字分别表示。）
 * 左减数字必须为一位，比如8写成VIII，而非IIX。
 * @author Yobol
 */
public class RomaAndArab {
    
    /**
     * 输入罗马字符串，转为阿拉伯数字
     * （假设输入和罗马字符都是符合规则的）
     * 
     * 基本思路：把罗马数字分段处理，从左到右，分段相加
     * 设置当前位current，前一位pre，分段值segment（每一段最长为4位）
     * 如果当前位和前一位数字相同，那么分段值为现有分段值加上当前值
     * 如果当前位小于前一位数字，那么分段值为当前值减去现有分段值
     * 如果当前位大于前一位数字，那么可以先将分段值加到结果中，然后重新记录分段值
     * 
     * @param roma
     * @return 
     */
    public int convertRomaToArab(String roma){
        if (roma.length() < 1){
            return 0;
        }
        
        int result = 0;
        int current;
        int pre = singleRomaToArab(roma.charAt(0));
        int segment = pre;
        // MMM   CM    LXXX    IV
        // 3000  900   80      4
        for (int i = 1; i < roma.length(); i++) {
            current = singleRomaToArab(roma.charAt(i));
            if (current == pre){
                segment += current;
            } else if (current > pre){
                segment = current - segment;
            } else if (current < pre){
                result += segment;
                segment = current;
            }
            pre = current;
        }  
        result += segment;
        return result;
    }
    
    private int singleRomaToArab(char r){
        switch(r){
            case 'I':
                return 1;
            case 'V':
                return 5;
            case 'X':
                return 10;
            case 'L':
                return 50;
            case 'C':
                return 100;
            case 'D':
                return 500;
            case 'M':
                return 1000;
            default:
                return 0;
        }
    }
    
    
    public static void main(String[] args) {
        RomaAndArab roma = new RomaAndArab();
        System.out.println(roma.convertRomaToArab("I"));//1
        System.out.println(roma.convertRomaToArab("II"));//2
        System.out.println(roma.convertRomaToArab("III"));//3
        System.out.println(roma.convertRomaToArab("IV"));//4
        System.out.println(roma.convertRomaToArab("V"));//5
        System.out.println(roma.convertRomaToArab("VI"));//6
        System.out.println(roma.convertRomaToArab("VII"));//7
        System.out.println(roma.convertRomaToArab("VIII"));//8
        System.out.println(roma.convertRomaToArab("IX"));//9
        System.out.println(roma.convertRomaToArab("X"));//10
        System.out.println(roma.convertRomaToArab("XI"));//11
        System.out.println(roma.convertRomaToArab("XII"));//12
        System.out.println(roma.convertRomaToArab("XIII"));//13
        System.out.println(roma.convertRomaToArab("XIV"));//14
        System.out.println(roma.convertRomaToArab("XV"));//15
        
        System.out.println(roma.convertRomaToArab("MMMCMLXXXIV"));//3984
    }
}
